package com.zenika.zentracker.hibernate.jdbc;

import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.SQLException;

import org.hibernate.HibernateException;
import org.hibernate.Interceptor;
import org.hibernate.ScrollMode;
import org.hibernate.jdbc.BatchingBatcher;
import org.hibernate.jdbc.ConnectionManager;

import com.zenika.zentracker.hibernate.ZenTrackerEmptyInterceptor;
import com.zenika.zentracker.hibernate.sql.ZenTrackerCallableStatementProxy;
import com.zenika.zentracker.hibernate.sql.ZenTrackerPreparedStatementProxy;

/**
 * 
 * Class extending the Hibernate BatchingBatcher. It's main goal is to wrap the creation of a <tt>PreparedStatement</tt>
 * or a <tt>CallableStatement</tt> and use a Proxy instead.
 * 
 * Two type of Proxy can be used:
 * 
 * <tt>ZenTrackerPreparedStatementProxy</tt>
 * <tt>ZenTrackerCallableStatementProxy</tt>
 * 
 * @see BatchingBatcher
 * @author Zenika
 */
public class ZenTrackerBatchingBatcher extends BatchingBatcher {

    private Interceptor interceptor = new ZenTrackerEmptyInterceptor();

    /**
     * Constructor using a ConnectionManager and an Interceptor.
     * 
     * @see BatchingBatcher
     * 
     * @param connectionManager
     * @param interceptor
     */
    public ZenTrackerBatchingBatcher(ConnectionManager connectionManager, Interceptor interceptor) {
        super(connectionManager, interceptor);
        this.interceptor = interceptor;
    }

    // No need to redefine the method: prepareStatement(String). Uses internally prepareStatement(String, boolean)
    // public PreparedStatement prepareStatement(String sql) throws SQLException, HibernateException {
    // return super.prepareStatement(sql);
    // }

    // No need to redefine the method. Uses internally prepareStatement(String, boolean)
    // public PreparedStatement prepareBatchStatement(String sql) throws SQLException, HibernateException {
    // return super.prepareBatchStatement(sql);
    // }

    /*
     * (non-Javadoc)
     * 
     * @see org.hibernate.jdbc.AbstractBatcher#prepareSelectStatement(java.lang.String)
     */
    public PreparedStatement prepareSelectStatement(String sql) throws SQLException, HibernateException {
        return new ZenTrackerPreparedStatementProxy(super.prepareSelectStatement(sql), interceptor, sql);
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.hibernate.jdbc.AbstractBatcher#prepareStatement(java.lang.String, boolean)
     */
    public PreparedStatement prepareStatement(String sql, boolean getGeneratedKeys) throws SQLException,
            HibernateException {
        return new ZenTrackerPreparedStatementProxy(super.prepareStatement(sql, getGeneratedKeys), interceptor, sql);
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.hibernate.jdbc.AbstractBatcher#prepareStatement(java.lang.String, java.lang.String[])
     */
    public PreparedStatement prepareStatement(String sql, String[] columnNames) throws SQLException, HibernateException {
        return new ZenTrackerPreparedStatementProxy(super.prepareStatement(sql, columnNames), interceptor, sql);
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.hibernate.jdbc.AbstractBatcher#prepareQueryStatement(java.lang.String, boolean,
     *      org.hibernate.ScrollMode)
     */
    public PreparedStatement prepareQueryStatement(String sql, boolean scrollable, ScrollMode scrollMode)
            throws SQLException, HibernateException {

        return new ZenTrackerPreparedStatementProxy(
                super.prepareQueryStatement(sql, scrollable, scrollMode),
                interceptor,
                sql);
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.hibernate.jdbc.AbstractBatcher#prepareCallableStatement(java.lang.String)
     */
    public CallableStatement prepareCallableStatement(String sql) throws SQLException, HibernateException {
        return new ZenTrackerCallableStatementProxy(super.prepareCallableStatement(sql), interceptor, sql);
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.hibernate.jdbc.AbstractBatcher#prepareCallableQueryStatement(java.lang.String, boolean,
     *      org.hibernate.ScrollMode)
     */
    public CallableStatement prepareCallableQueryStatement(String sql, boolean scrollable, ScrollMode scrollMode)
            throws SQLException, HibernateException {

        return new ZenTrackerCallableStatementProxy(
                super.prepareCallableQueryStatement(sql, scrollable, scrollMode),
                interceptor,
                sql);
    }

}
